package se.webbzon.boltzmann.game.object.dialogue;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import se.webbzon.boltzmann.game.object.dialogue.factory.AbstractDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.ColoredDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.DynamicDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.HugeDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.ImageDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.InputDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.NewLineDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.OscillatingDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.SmallDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.factory.TremblingDialogueWordFactory;
import se.webbzon.boltzmann.game.object.dialogue.layout.DialogueLayout;
import se.webbzon.boltzmann.game.object.dialogue.word.ColoredDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.AbstractDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.DynamicDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.HugeDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.ImageDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.InputDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.NewLineDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.OscillatingDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.SmallDialogueWord;
import se.webbzon.boltzmann.game.object.dialogue.word.TremblingDialogueWord;

public class DialogueTextParser {
	
	// The color of a keyword
	public static final Color keywordColor = new Color(128,0,0);
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Parses a dialogue text into a list of abstract dialogue word factories. **/
	public static List<AbstractDialogueWordFactory> compile(String text) {
		ArrayList<AbstractDialogueWordFactory> factories = 
				new ArrayList<AbstractDialogueWordFactory>();
		parseInner(text,0,'P',new FactoryCreator(),factories);
		return factories;
	}
	
	/** Parses a dialogue text into a list of abstract dialogue words. **/
	public static List<AbstractDialogueWord> parse(DialogueLayout layout, String text) {
		ArrayList<AbstractDialogueWord> words = new ArrayList<AbstractDialogueWord>();
		parseInner(text,0,'P',new WordCreator(layout), words);
		return words;
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** An inner help function to the method parse(String text). **/
	private static <T> void parseInner(	String text,
										int index,
										char block,
										Creator<T> creator,
										Collection<T> objects) {
		StringBuilder builder = new StringBuilder();
		// Set to true if the cursor is inside "<" and ">"
		boolean insideBlock = false;
		char c = 0;
		
		for (int i = index; i < text.length(); i++) {
			c = text.charAt(i);
			switch (c) {
			case '#':
				if (builder.length() > 0)
					objects.add(creator.create(block,builder.toString()));
				objects.add(creator.create('#',builder.toString()));
				builder = new StringBuilder();
				break;
			case '<':
				if (builder.length() > 0)
					objects.add(creator.create(block,builder.toString()));
				insideBlock = true;
				break;
			case '>':
				parseInner(text,i+1,block,creator,objects);
				return;
			default:
				if (!insideBlock)
					builder.append(c);
				else
					block = c;
			}
		}
		
		// Add the word if the end of the string was reached
		if (c != 0 && builder.length() > 0)
			objects.add(creator.create(block,builder.toString()));
	}
	
	/*============================================================
	Private Interfaces
	============================================================*/
	
	private static interface Creator<T> {
		
		/*============================================================
		Public Methods
		============================================================*/
		
		/** Creates a new object of a given type defined by the
		 * block name with a given text. **/
		public T create(char blockName, String text);
		
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private static class WordCreator implements Creator<AbstractDialogueWord> {
		
		private final DialogueLayout layout;
		
		/*============================================================
		Constructors
		============================================================*/
		
		public WordCreator(DialogueLayout layout) {
			this.layout = layout;
		}
		
		/*============================================================
		Public Methods
		============================================================*/

		@Override public AbstractDialogueWord create(char blockName, String text) {
			switch (blockName) {
			case 'A':
				return new InputDialogueWord(layout,text);
			case 'D':
				return new DynamicDialogueWord(layout,text);
			case 'H':
				return new HugeDialogueWord(layout,text);
			case 'I':
				return new ImageDialogueWord(layout,text);
			case 'K':
				return new ColoredDialogueWord(layout,text,keywordColor);
			case 'O':
				return new OscillatingDialogueWord(layout,text);
			case 'P':
				return new ColoredDialogueWord(layout,text);
			case 'S':
				return new SmallDialogueWord(layout,text);
			case 'T':
				return new TremblingDialogueWord(layout,text);
			case '#':
				return new NewLineDialogueWord();
			default: 
				return new ColoredDialogueWord(layout,text);
			}
		}
		
	}
	
	private static class FactoryCreator implements Creator<AbstractDialogueWordFactory> {
		
		@Override public AbstractDialogueWordFactory create(char blockName, String text) {
			switch (blockName) {
			case 'A':
				return new InputDialogueWordFactory(text);
			case 'D':
				return new DynamicDialogueWordFactory(text);
			case 'H':
				return new HugeDialogueWordFactory(text);
			case 'I':
				return new ImageDialogueWordFactory(text);
			case 'K':
				return new ColoredDialogueWordFactory(text,keywordColor);
			case 'O':
				return new OscillatingDialogueWordFactory(text);
			case 'P':
				return new ColoredDialogueWordFactory(text);
			case 'S':
				return new SmallDialogueWordFactory(text);
			case 'T':
				return new TremblingDialogueWordFactory(text);
			case '#':
				return new NewLineDialogueWordFactory();
			default: 
				return new ColoredDialogueWordFactory(text);
			}
		}
		
	}

}
